

#include "typedef.h"
#include"lpc_data_type.h"
#include "Driver_I2c.h"
#include "i2c_module_interface.h"
#include "Os.h"
#include "IicDriverTester.h"
#include "Debug.h"
#include "MmcDef.h"

uint8 g_FruDeviceBuffer[MAX_FRUINFO_SIZE];
uint32 g_FruReadCounter = 0;
uint32 g_ConfigReadCounter = 0;


IicDriver* g_pIicDriverArray[MAX_IICDRIVER] = {&g_MmcIpmbLIicDriver, &g_IicDriverLocal};

uint8 g_IpmbTxFailedCounter = 0;

void IicDriver_Init(IicDriver* pIicDriver, uint8 channel)
{
	Trace("%s(channel=%d)\n", _FUNC_, channel);
	memset(pIicDriver, 0, sizeof(IicDriver));
	
	pIicDriver->m_Channel = channel;

}

IicDriver* IicDriver_Get(uint8 channel)
{
	int i = 0;
	uint32* pValue  = Null;
	IicDriver* pIicDriver = Null;

	for(i = 0; i < sizeof(g_pIicDriverArray)/4; i++)
	{
		pIicDriver = g_pIicDriverArray[i];

		pValue = (uint32*)QUEUE_popGetHead(&pIicDriver->m_EventQueue);
		if(channel == pIicDriver->m_Channel)
		{
			return pIicDriver;
		}
	}
	return Null;
}

int I2C_Config(uint8 ChanNum,uint8 RxBufNum,uint8 TOValue)
{
	if(ChanNum ==I2C_CHANNEL_LOCAL)
	{
		//IicDriverTester_Init(&g_IicDriverLocal, ChanNum, &g_LocalQueue, &g_LocalQueue);
	}
	else if(ChanNum ==I2C_CHANNEL_IPMBL)
	{
		//IicDriverTester_Init(&g_MmcIpmbLIicDriver, ChanNum, &g_CmToMmcQueue, &g_MmcToCmQueue);
	}
	else
	{
		Assert(False);
	}

    return 0;
}

int I2C_RegClient(uint8 ChanNum,uint8 EventMask,void * I2C_CallBack,uint8 AdrLen,uint8 * AdrList)
{
	IicDriver* pIicDriver = IicDriver_Get(ChanNum);

	if(pIicDriver)
	{
		pIicDriver->Notify = (IicDriverNotifyFun)I2C_CallBack;
	}
	else
	{
		Assert(False);
	}

    return 0;
}


int I2C_TxDataEx(uint8 ChanNum,uint8 DataLen,void * DataBuf)
{
	return I2C_TxData(ChanNum,DataLen,DataBuf);
}

int I2C_TxData(uint8 ChanNum,uint8 DataLen,void * DataBuf)
{
	uint8* pData = (uint8*)DataBuf;
	uint32 m_Interrupt = 0;
	IicDriver* pIicDriver = IicDriver_Get(ChanNum);
	BusDataPacket packet;

	if(Null == pIicDriver)
	{
		Assert(False);
		return 0;
	}

	if(ChanNum == I2C_CHANNEL_LOCAL)
	{
		uint16 offset = (pData[1]<<8) | pData[2];
 		memcpy(&g_FruDeviceBuffer[offset], &pData[3], DataLen-3);
		return DataLen;
	}

	if(g_IpmbTxFailedCounter)
	{
		g_IpmbTxFailedCounter--;
		return 0;
	}

	if(!QUEUE_isFull(pIicDriver->m_pTxQueue))
	{
		if(DataLen > BUS_DATAPACKET_SIZE)
		{
			Assert(DataLen < BUS_DATAPACKET_SIZE);
			return 0;
		}

		memcpy(packet.m_Data, DataBuf, DataLen);
		packet.m_Len = DataLen;
		QUEUE_add(pIicDriver->m_pTxQueue,&packet);

		//Create a IIC Event
		m_Interrupt = EVENT_TXOK_MASK;
		Assert(!QUEUE_isFull(&pIicDriver->m_EventQueue));
		QUEUE_add(&pIicDriver->m_EventQueue, &m_Interrupt);
	}
	else
	{
		DataLen = 0; 
	}

    return DataLen;
}

int I2C_RxData(uint8 ChanNum,uint8 MaxLen,void * DataBuf)
{
	int nLen = 0;
	IicDriver* pIicDriver = IicDriver_Get(ChanNum);
	BusDataPacket* pBusDataPacket = Null;

	if(Null == pIicDriver)
	{
		Assert(False);
		return 0;
	}

	pBusDataPacket = (BusDataPacket*)QUEUE_popGetHead(pIicDriver->m_pRxQueue);

	if(pBusDataPacket)
	{
		nLen = pBusDataPacket->m_Len;
		if(MaxLen < nLen)
		{
			nLen = MaxLen;
		}
		memcpy(DataBuf, (uint8*)pBusDataPacket->m_Data, nLen);
	}

	return nLen;
}
I2cDeviceReadFun I2c_Device_Read_Ex = Null;
int  I2c_Device_Read(uint8 ChanNum,uint8 *SendData,uint8 SendLen,uint8 *RecvData,uint8 RecvLen)
{
	uint8 addr = SendData[0];
	uint16 offset = (SendData[1] << 8) | SendData[2] ;

	if(offset == FRU_REPOSITORY_ADDR)
	{
		g_FruReadCounter++;
	}
	else if(offset == SDR_REPOSITORY_ADDR)
	{
		g_ConfigReadCounter++;
	}

	if(I2c_Device_Read_Ex)
	{
		return I2c_Device_Read_Ex(ChanNum, SendData, SendLen, RecvData, RecvLen);
	}
	else
	{
 		memcpy(&RecvData[1], &g_FruDeviceBuffer[offset], RecvLen);
	}
    return RecvLen;
}

int I2C_GetStatus(uint8 ChanNum,uint8 * RxBufStatus,uint8 * TxBufStatus,uint8 * EventStatus)
{    
	IicDriver* pIicDriver = IicDriver_Get(ChanNum);

	if(Null == pIicDriver)
	{
		Assert(False);
		return -1;
	}

	if(QUEUE_isEmpty(pIicDriver->m_pRxQueue))
	{
		*RxBufStatus = STATUS_BUF_EMPT;
	}
	else
	{
		*RxBufStatus = STATUS_BUF_FULL;
	}

	if(QUEUE_isFull(pIicDriver->m_pTxQueue))
	{
		*TxBufStatus = STATUS_BUF_FULL;
	}
	else
	{
		*TxBufStatus = STATUS_BUF_EMPT;
	}

    return 0;        //success get
}

